﻿using System;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Threading.Tasks;
using WordpressRestApi;

namespace ApiClientTest
{
    /// <summary>Test <see cref="PostClient"/>.</summary>
    [TestClass]
    public class PostClientTest : ClientTestBase
    {
        [TestMethod]
        public async Task GetAllPosts()
        {
            var client = CreateClient();
            var query = client.Post.GetAllPosts();
            var posts = await query.ToArrayAsync();

            Assert.IsTrue(posts.Length >= 0);
        }

        [TestMethod]
        public async Task GetPostsWithFields()
        {
            var client = CreateClient();
            var filter = new PostParametrization { Fields = new[] { PostField.ID, PostField.Title } };
            var query = client.Post.GetPosts(filter);
            var posts = await query.ToArrayAsync();

            foreach (var p in posts)
            {
                Assert.IsNotNull(p.ID, "ID");
                Assert.IsTrue(!string.IsNullOrWhiteSpace(p.Title), "Title");
            }
        }

        //  Ignore since there seems to be a discrepency between lexicographic comparison of Wordpress & .NET
        //  Also, there seems to be an error on how the sort of date is handled:  dates are sorted regardless of
        //  their timezone
        [TestMethod]
        [Ignore]
        public async Task GetPostsOrderBy()
        {
            var client = CreateClient();
            var filter = new PostParametrization
            {
                Fields = new[] { PostField.Date },
                OrderByAscending = true,
                OrderByField = PostField.Date
            };
            var query = client.Post.GetPosts(filter);
            var posts = await query.Select(p => p.Date).ToArrayAsync();
            var skipFirst = posts.Skip(1);
            var skipLast = posts.Take(posts.Length - 1);
            var paired = skipFirst.Zip(skipLast, (i, j) => Tuple.Create(i, j));
            var tested = from p in paired
                         where p.Item1 < p.Item2
                         select p;
            var firstFailure = tested.FirstOrDefault();

            Assert.IsNull(
                firstFailure,
                firstFailure != null ? $"{firstFailure.Item2} & {firstFailure.Item1}" : string.Empty);
        }

        [TestMethod]
        public async Task GetPostsWithFieldsProjectedFiltered()
        {
            var client = CreateClient();
            var filter = new PostParametrization { Fields = new[] { PostField.ID, PostField.Title, PostField.Status } };
            var query = client.Post.GetPosts(filter)
                .Where(p => p.Status == PostStatus.Publish)
                .Select(p => new { ID = p.ID, Title = p.Title });
            var posts = await query.ToArrayAsync();

            foreach (var p in posts)
            {
                Assert.IsNotNull(p.ID, "ID");
                Assert.IsTrue(!string.IsNullOrWhiteSpace(p.Title), "Title");
            }
        }

        [TestMethod]
        public async Task GetPostsByTag()
        {
            var client = CreateClient();
            var allTags = await client.Tag.GetAllTags().ToArrayAsync();
            var nonEmptyTag = (from t in allTags
                               where t.PostCount > 0
                               select t).FirstOrDefault();

            if (nonEmptyTag != null)
            {
                var posts = await client.Post.GetPosts(new PostParametrization
                {
                    TagSlug = nonEmptyTag.Slug
                }).ToArrayAsync();

                Assert.AreEqual(nonEmptyTag.PostCount, posts.Length, "# posts");
            }
        }

        #region Update Tags, done on a specific Post ID
        [TestMethod]
        [Ignore]
        public async Task UpdateTags()
        {
            const int POST_ID = 1213;

            var client = CreateClient();
            var tagSlugs = new[] { "ADFS", "Agile", "Architecture" };
            var post = await client.Post.UpdateTagsAsync(POST_ID, tagSlugs);

            Assert.AreEqual(POST_ID, post.ID, "Post ID");
            Assert.AreEqual(tagSlugs.Length, post.Tags.Count, "# of tags");
            foreach (var slug in tagSlugs)
            {
                Assert.IsTrue(post.Tags.ContainsKey(slug), "Slug:  " + slug);
            }

            post = await client.Post.UpdateTagsAsync(POST_ID, null);

            Assert.AreEqual(POST_ID, post.ID, "Post ID - removed");
            Assert.AreEqual(0, post.Tags.Count, "# of tags - removed");
        }
        #endregion
    }
}